package com.hksj.Intelligentmanagement.auth.manager;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.hksj.Intelligentmanagement.auth.entity.LoginUser;
import com.hksj.Intelligentmanagement.utils.JwtUtil;
import com.hksj.Intelligentmanagement.utils.RedisCache;
import io.jsonwebtoken.Claims;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.concurrent.TimeUnit;

@Component
public class TokenManager {

    public static final String PREFIX = "login:";
    public static final String SEPARATOR = ":";

    @Autowired
    private RedisCache<LoginUser> redisCache;

    @Value("${token.login.is-concurrent:true}")
    private Boolean isConcurrent;

    /**
     * 登录信息缓存
     * @param loginUser 登录用户信息
     * @param expire 过期时间 单位小时
     * @return
     */
    public String createToken(LoginUser loginUser, Integer expire){
        //用户id
        String userId = loginUser.getUser().getId();
        //redis token key 后缀
        String suffix = "";
        if (isConcurrent){
            suffix = IdUtil.fastSimpleUUID();
        }
        //存在登录用户信息中
        loginUser.setAdditional(suffix);
        //获取redis key
        String loginCacheKey = getLoginCacheKey(userId, suffix);
        //添加缓存
        redisCache.setCacheObject(loginCacheKey, loginUser,expire, TimeUnit.HOURS);
        //创建token
        return createToken(userId,suffix);
    }

    /**
     * 创建返回给前端的jwt token
     * @param userId
     * @param suffix
     * @return
     */
    public String createToken(String userId , String suffix){
        //将token信息转成json字符串
        String original =  JSONObject.toJSONString(new TokenInfo(userId,suffix));
        return JwtUtil.createJWT(original);
    }

    /**
     * 退出登录或踢人下线
     * @param loginUser 登录用户信息
     */
    public void logout(LoginUser loginUser){
        String userId = loginUser.getUser().getId();
        String suffix = loginUser.getAdditional(String.class);
        String loginCacheKey = getLoginCacheKey(userId, suffix);
        //删除缓存对象
        redisCache.deleteObject(loginCacheKey);
    }

    /**
     * 踢人下线
     * @param userId 用户id
     */
    public void kick(String userId){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(PREFIX).append(userId).append("*");
        Collection<String> keys = redisCache.keys(stringBuffer.toString());
        for (String key : keys) {
            redisCache.deleteObject(key);
        }
    }

    /**
     * 通过token 获取登录用户信息
     * @param jwtToken token
     * @return
     */
    public LoginUser getUserInfo(String jwtToken){
        TokenInfo tokenInfo = null;
        try {
            //解密
            Claims claims = JwtUtil.parseJWT(jwtToken);
            String original = claims.getSubject();
            tokenInfo = JSONObject.parseObject(original, TokenInfo.class);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }
        if (ObjectUtil.isNull(tokenInfo)){
            return null;
        }
        //获取redis token key
        String loginCacheKey = getLoginCacheKey(tokenInfo.getUserId(), tokenInfo.getSuffix());
        //获取缓存对象
        LoginUser loginUser = redisCache.getCacheObject(loginCacheKey);
        return loginUser;
    }

    public String getLoginCacheKey(String userId,String suffix){
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(PREFIX).append(userId);
        if (isConcurrent){
            stringBuffer.append(SEPARATOR).append(suffix);
        }
        return stringBuffer.toString();
    }

    @Data
    public class TokenInfo{

        public TokenInfo(String userId, String suffix) {
            this.userId = userId;
            this.suffix = suffix;
        }

        /**
         * 用户id
         */
        private String userId;

        /**
         * 随机不重复字符串
         */
        private String suffix;
    }
}
